/****
	Copyright 2012 Taras Kulbachka

	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at

		http://www.apache.org/licenses/LICENSE-2.0

	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.
*/
package com.atdevsoft.apps.abyss;

import android.database.Cursor;

public class QuotesNavigator {
	public static final int QUOTES_PER_PAGE = 30;
	public static final int VERY_FIRST_QUOTE = 0;
	public static final int VERY_LAST_QUOTE = -1;
	
    public interface OnPageChangedListener {
    	void onPageChanged(int newPage, int quotesOnThisPage);
        void onJumpToPage(int newPage);
    }		
	
	private int mCurrentFirstQuote;
	private int mCurrentQuotesOnPage;
	private int mCurrentLastQuote;
	private int mCurrentPage;
	private int mTotalPages;    
    private Cursor mCurrentPageCursor;
    
    private String mCurrentQuotesTable = "";
    private OnPageChangedListener mOnPageChangedListener;
	
    
    private int getTotalPages(int quotesBeforeThis) {
        Cursor getTotPage = DatabaseHelper.rawQuery("select count(*) from " + mCurrentQuotesTable, null);
        getTotPage.moveToFirst();
        int totalQuotes = getTotPage.getInt(0);
        int pages = (int)Math.ceil((double)totalQuotes/QUOTES_PER_PAGE);
        if ((int)Math.ceil((double)(totalQuotes - quotesBeforeThis)/QUOTES_PER_PAGE) + 
        		(int)Math.ceil((double)(quotesBeforeThis)/QUOTES_PER_PAGE) > pages) {
        	pages++;
        }
        getTotPage.close();
    	return pages;
    }
    
    private Cursor getCursor(int topQuote, int bottomQuote, boolean exactly) {
    	String query;
    	int quotesPerPage = QUOTES_PER_PAGE + 1;
    	if (exactly)
    		quotesPerPage = QUOTES_PER_PAGE;    	
    	if ((topQuote == 0) && (bottomQuote == 0)) // set quotes from the first (max id) we have
    		query = "select " + DatabaseHelper.QUOTES_ID + ", " + DatabaseHelper.QUOTES_SOURCE_ID + ", " +
    				DatabaseHelper.QUOTES_POSTED + ", " + DatabaseHelper.QUOTES_QUOTE + ", " + DatabaseHelper.QUOTES_ADDED_TO_FAVS +
    				" from " + mCurrentQuotesTable + 
    				" order by 2 desc limit 0, " + String.valueOf(quotesPerPage);
    	else if (topQuote != 0) // set quotes starting from the topQuote and QUOTES_PER_PAGE + 1 count
    		query = "select " + DatabaseHelper.QUOTES_ID + ", " + DatabaseHelper.QUOTES_SOURCE_ID + ", " +
    				DatabaseHelper.QUOTES_POSTED + ", " + DatabaseHelper.QUOTES_QUOTE + ", " + DatabaseHelper.QUOTES_ADDED_TO_FAVS +
    				" from " + mCurrentQuotesTable + 
    				" where " + DatabaseHelper.QUOTES_SOURCE_ID + " <= " + String.valueOf(topQuote) +
    				" order by 2 desc limit 0, " + String.valueOf(quotesPerPage);    	
    	else {// set quotes starting from the bottomQuote - QUOTES_PER_PAGE
    		  // BUT! if there are less quotes than bottomQuote - QUOTES_PER_PAGE in DB, we need to add more of them coming after bottomQuote
    		  // to have next button. Union is used for that part
    		  // we also have nested select here because we need to have set of quotes limited from the bottom of the sort order
    		if (mCurrentPage > 2) {
    			query = "select " + DatabaseHelper.QUOTES_ID + ", " + DatabaseHelper.QUOTES_SOURCE_ID + ", " +
	    				DatabaseHelper.QUOTES_POSTED + ", " + DatabaseHelper.QUOTES_QUOTE + ", " + DatabaseHelper.QUOTES_ADDED_TO_FAVS + 
	    				" from " + mCurrentQuotesTable + 
	    				" where " + DatabaseHelper.QUOTES_SOURCE_ID + " in " +
	    				"(select " + DatabaseHelper.QUOTES_SOURCE_ID + " from " + mCurrentQuotesTable +
	    				" where " + DatabaseHelper.QUOTES_SOURCE_ID + " >= " + String.valueOf(bottomQuote) + 
	    				" order by 1 asc limit 0, " + String.valueOf(quotesPerPage) + 	    				
	    				" ) order by 2 desc";
    		} else {
	    		query = "select " + DatabaseHelper.QUOTES_ID + ", " + DatabaseHelper.QUOTES_SOURCE_ID + ", " +
	    				DatabaseHelper.QUOTES_POSTED + ", " + DatabaseHelper.QUOTES_QUOTE + ", " + DatabaseHelper.QUOTES_ADDED_TO_FAVS +
	    				" from " + mCurrentQuotesTable + 
	    				" where " + DatabaseHelper.QUOTES_SOURCE_ID + " in " +
	    				"(select " + DatabaseHelper.QUOTES_SOURCE_ID + " from " + mCurrentQuotesTable +
	    				" where " + DatabaseHelper.QUOTES_SOURCE_ID + " >= " + String.valueOf(bottomQuote) + 
	    				" order by 1 asc limit 0, " + String.valueOf(quotesPerPage) + ") " +
	    				"union all select " + DatabaseHelper.QUOTES_ID + ", " + DatabaseHelper.QUOTES_SOURCE_ID + ", " +
	    				DatabaseHelper.QUOTES_POSTED + ", " + DatabaseHelper.QUOTES_QUOTE + ", " + DatabaseHelper.QUOTES_ADDED_TO_FAVS +
	    				" from " + mCurrentQuotesTable + 
	    				" where " + DatabaseHelper.QUOTES_SOURCE_ID + " < " + String.valueOf(bottomQuote) +
	    				" order by 2 desc limit 0, " + String.valueOf(quotesPerPage);
    		}
    	}
    	
        Cursor cursor = DatabaseHelper.rawQuery(query, null);
        
        return cursor;
    }
    
    private void setPage(int topQuote, int bottomQuote, boolean exactly) {
    	Cursor cursor = getCursor(topQuote, bottomQuote, exactly);
    	
        if ((cursor == null) || (cursor.getCount() <= 0)) {
            if (mOnPageChangedListener != null)
            	mOnPageChangedListener.onPageChanged(0, 0);
            if (cursor != null)
            	cursor.close();
        	mCurrentPageCursor = null;
        	mTotalPages = 0;
        	mCurrentQuotesOnPage = 0;
        	return;
        }
        
        mCurrentPageCursor = cursor;

        cursor.moveToLast();        
        mCurrentLastQuote = cursor.getInt(cursor.getColumnIndex(DatabaseHelper.QUOTES_SOURCE_ID));
        cursor.moveToFirst();
        mCurrentFirstQuote = cursor.getInt(cursor.getColumnIndex(DatabaseHelper.QUOTES_SOURCE_ID));
        
        mCurrentQuotesOnPage = cursor.getCount();
        
        if ((mCurrentPage < 0) || (mTotalPages < 0) || (mCurrentPage == 1)) {
        	Cursor getCurrPage = DatabaseHelper.rawQuery("select count(*) from " + mCurrentQuotesTable + " where " + 
        			DatabaseHelper.QUOTES_SOURCE_ID + " > " + String.valueOf(mCurrentFirstQuote), null);
        	getCurrPage.moveToFirst();
        	int quotesBeforeThis = getCurrPage.getInt(0);
        	mCurrentPage = (int)Math.ceil((double)quotesBeforeThis/QUOTES_PER_PAGE) + 1;
        	getCurrPage.close();
        
        	if ((mTotalPages < 0) || (mCurrentPage == 1))
        		mTotalPages = getTotalPages(quotesBeforeThis);
        }
        if (mCurrentPage > mTotalPages) // because we may start from the middle of the page, mCurrentPage > mTotalPages is real but strange for user
        	mCurrentPage = mTotalPages;
        
        int cqop = mCurrentQuotesOnPage;
        if (mCurrentQuotesOnPage > QUOTES_PER_PAGE)
        	cqop = QUOTES_PER_PAGE;
        
        if (mOnPageChangedListener != null)
        	mOnPageChangedListener.onPageChanged(mCurrentPage, cqop);
    }
    
    private void setQuotesTable(String newTable) {
    	mCurrentQuotesTable = newTable;
    	    	
        mCurrentFirstQuote = -1;
        mCurrentPage = -1;
        mCurrentQuotesOnPage = -1;  
        mTotalPages = -1;        
    }    
    
	public QuotesNavigator() {
		mOnPageChangedListener = null;
	}
	
	public void setOnPageChangedListener(OnPageChangedListener listener) {
		mOnPageChangedListener = listener;
	}
	
	
	public void navigateNextPage() {		
		if (mCurrentQuotesOnPage > QUOTES_PER_PAGE) {
			mCurrentPage++;
			setPage(mCurrentLastQuote, 0, false);    
		}
	}
	
	public void navigatePrevPage() {
		if (mCurrentPage > 1) {
			mCurrentPage--;
			setPage(0, mCurrentFirstQuote, false);
		}
	}	
	
	public void setCurrentTable(String tableName, int topQuoteId) {
		setQuotesTable(tableName);
		mCurrentPage = -1;
		
		if (topQuoteId != VERY_LAST_QUOTE) {
			setPage(topQuoteId, 0, false);
		} else {
			setPage(0, 1, true);
		}
		
		if (mOnPageChangedListener != null)
			mOnPageChangedListener.onJumpToPage(mCurrentPage);
	}
	
	public String getCurrentTableName() {
		return mCurrentQuotesTable;
	}	

	public void setTopQuoteByPageNum(int pageNum) {
        Cursor getQuoteNum = DatabaseHelper.rawQuery("select " + DatabaseHelper.QUOTES_SOURCE_ID + " from " + 
        		mCurrentQuotesTable + " order by 1 desc limit " + 
        		String.valueOf(QUOTES_PER_PAGE*(pageNum - 1)) + ", 1", null);
        mTotalPages = -1;        
        if (getQuoteNum.getCount() == 0) {
        	setTopQuote(VERY_FIRST_QUOTE); 
        } else {
            getQuoteNum.moveToFirst();        
            int quoteStart = getQuoteNum.getInt(0);
            getQuoteNum.close();
            setTopQuote(quoteStart);    		
        }		
	}
	
	
	public void setTopQuote(int topQuoteId) {
		mCurrentPage = -1;
		if (topQuoteId != VERY_LAST_QUOTE) {
			setPage(topQuoteId, 0, false);
		} else {
			setPage(0, 1, true);
		}		
		
		if (mOnPageChangedListener != null)
			mOnPageChangedListener.onJumpToPage(mCurrentPage);
	}
	
	public int getTopQuote() {
		return mCurrentFirstQuote;
	}
	
	public int getTotalPagesCount() {
		return mTotalPages;
	}
	
	public int getCurrentPageNumber() {
		return mCurrentPage;
	}
	
	public Cursor getCurrentPageCursor() {
		return mCurrentPageCursor;
	}
	
	public Cursor getNextPageCursor() {
		return getCursor(mCurrentLastQuote, 0, false);
	}
	
	public Cursor getPrevPageCursor() {
		return getCursor(0, mCurrentFirstQuote, false);
	}	
}